package com.weijianhuawen.wjblog.web.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.common.collect.Lists;
import com.weijianhuawen.wjblog.common.utils.PageResponse;
import com.weijianhuawen.wjblog.search.config.LuceneProperties;
import com.weijianhuawen.wjblog.search.helper.LuceneHelper;
import com.weijianhuawen.wjblog.search.index.ArticleIndex;
import com.weijianhuawen.wjblog.web.mode.vo.search.SearchArticlePageListReqVo;
import com.weijianhuawen.wjblog.web.mode.vo.search.SearchArticlePageListRspVo;
import com.weijianhuawen.wjblog.web.service.SearchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.StringReader;
import java.lang.annotation.Documented;
import java.util.Collection;
import java.util.List;

/**
 * @version: java version 8
 * @Author: weijianhuawen
 * @description:
 * @date: 2024-11-05 12:39
 */

@Service
@Slf4j
public class SearchServiceImpl implements SearchService {
    @Autowired
    private LuceneProperties luceneProperties;
    @Autowired
    private LuceneHelper luceneHelper;
    @Override
    public PageResponse searchArticlePageList(SearchArticlePageListReqVo vo) {
        // 获取当前页码
        Integer current = Math.toIntExact(vo.getCurrent());
        Integer size = Math.toIntExact(vo.getSize());

        // 文章索引存放目录
        String articleIndex = ArticleIndex.NAME;
        // 查询关键词
        String word = vo.getWord();
        // 搜索的字段 标题 摘要 时间
        String[] columns = {ArticleIndex.COLUMN_TITLE, ArticleIndex.COLUMN_SUMMARY, ArticleIndex.COLUMN_CREATE_TIME};

        // 查询记录总数
        Long total = luceneHelper.searchTotal(articleIndex, word, columns);

        // 执行分页搜索
        List<Document> documents = luceneHelper.search(articleIndex, word, columns, current, size);

        // 如果查询结果为空直接返回
        if (CollectionUtils.isEmpty(documents)) {
            return PageResponse.success(Long.valueOf(current), Long.valueOf(size), total, null);
        }

        // 关键词高亮处理
        // 中文分析器
        Analyzer analyzer = new SmartChineseAnalyzer();
        QueryParser parser = new QueryParser(ArticleIndex.COLUMN_TITLE, analyzer);
        Query query = null;

        try {
            query = parser.parse(word);
        }catch (Exception e) {
            log.error("【搜索服务】 解析关键词失败！");
        }

        // 创建高亮器
        SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<span style=\"color: #f73131\">", "</span>");
        Highlighter highlighter = new Highlighter(formatter, new QueryScorer(query));

        // 返回vo
        List<SearchArticlePageListRspVo> vos = Lists.newArrayList();

        // 遍历查询到的文档
        documents.forEach(document -> {
            try {
                // 文章标题
                String title = document.get(ArticleIndex.COLUMN_TITLE);


                // 获取高亮片段
                TokenStream tokenStream = analyzer.tokenStream(ArticleIndex.COLUMN_TITLE, new StringReader(title));
                String titleFragment = highlighter.getBestFragment(tokenStream, title);

                // 没有匹配到关键词
                String hightlightedTitle = StringUtils.isNoneBlank(titleFragment) ? titleFragment : title;

                String id = document.get(ArticleIndex.COLUMN_ID);
                String cover = document.get(ArticleIndex.COLUMN_COVER);
                String summary = document.get(ArticleIndex.COLUMN_SUMMARY);
                String createTime = document.get(ArticleIndex.COLUMN_CREATE_TIME);

                // 组装vo
                SearchArticlePageListRspVo searchArticlePageListRspVo = SearchArticlePageListRspVo
                        .builder()
                        .cover(cover)
                        .createDate(createTime)
                        .id(Long.valueOf(id))
                        .summary(summary)
                        .title(hightlightedTitle)
                        .build();
                vos.add(searchArticlePageListRspVo);
            } catch (Exception e) {
                log.error("【搜索服务】 高亮格式转换异常！");
            }
        });
        return PageResponse.success(Long.valueOf(current), Long.valueOf(size), total, vos);
    }
}
